home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dtl
/
dv2dt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-09
|
19KB
|
912 lines
/* dv2dt - convert DVI file to human-readable "DTL" format.
- (ANSI C) version 0.5.1 - 19:09 GMT +11 Thu 9 Feb 1995
- author: Geoffrey Tobin ecsgrt@luxor.latrobe.edu.au
- patch: Michal Tomczak-Jaegermann ntomczak@vm.ucs.ualberta.ca
- Reference: "The DVI Driver Standard, Level 0",
by The TUG DVI Driver Standards Committee.
Appendix A, "Device-Independent File Format".
*/
/* unix version; read from stdin, write to stdout, by default. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dtl.h"
#define PRINT_BCOM if (group) fprintf (dtl, "%s", BCOM)
#define PRINT_ECOM if (group) fprintf (dtl, "%s", ECOM)
/*
operation's:
opcode,
name,
number of args,
string of arguments.
*/
struct op_info_st {int code; char * name; int nargs; char * args; };
typedef struct op_info_st op_info;
/*
table's:
name,
first opcode,
last opcode,
pointer to opcode info.
*/
struct op_table_st {char * name; int first; int last; op_info * list; };
typedef struct op_table_st op_table;
/* Table for opcodes 128 to 170 inclusive. */
op_info op_info_128_170 [] =
{
{128, "s1", 1, "1"},
{129, "s2", 1, "2"},
{130, "s3", 1, "3"},
{131, "s4", 1, "-4"},
{132, "sr", 2, "-4 -4"},
{133, "p1", 1, "1"},
{134, "p2", 1, "2"},
{135, "p3", 1, "3"},
{136, "p4", 1, "-4"},
{137, "pr", 2, "-4 -4"},
{138, "nop", 0, ""},
{139, "bop", 11, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
{140, "eop", 0, ""},
{141, "[", 0, ""},
{142, "]", 0, ""},
{143, "r1", 1, "-1"},
{144, "r2", 1, "-2"},
{145, "r3", 1, "-3"},
{146, "r4", 1, "-4"},
{147, "w0", 0, ""},
{148, "w1", 1, "-1"},
{149, "w2", 1, "-2"},
{150, "w3", 1, "-3"},
{151, "w4", 1, "-4"},
{152, "x0", 0, ""},
{153, "x1", 1, "-1"},
{154, "x2", 1, "-2"},
{155, "x3", 1, "-3"},
{156, "x4", 1, "-4"},
{157, "d1", 1, "-1"},
{158, "d2", 1, "-2"},
{159, "d3", 1, "-3"},
{160, "d4", 1, "-4"},
{161, "y0", 0, ""},
{162, "y1", 1, "-1"},
{163, "y2", 1, "-2"},
{164, "y3", 1, "-3"},
{165, "y4", 1, "-4"},
{166, "z0", 0, ""},
{167, "z1", 1, "-1"},
{168, "z2", 1, "-2"},
{169, "z3", 1, "-3"},
{170, "z4", 1, "-4"}
}; /* op_info op_info_128_170 [] */
op_table op_128_170 = {"op_128_170", 128, 170, op_info_128_170};
/* Table for font with 1 to 4 bytes (opcodes 235 to 238) inclusive. */
op_info fnt_n [] =
{
{235, "f1", 1, "1"},
{236, "f2", 1, "2"},
{237, "f3", 1, "3"},
{238, "f4", 1, "-4"}
}; /* op_info fnt_n [] */
op_table fnt = {"f", 235, 238, fnt_n};
/* function prototypes */
int open_dvi __((char * dvi_file, FILE ** dvi));
int open_dtl __((char * dtl_file, FILE ** dtl));
int dv2dt __((FILE * dvi, FILE * dtl));
COUNT wunsigned __((int n, FILE * dvi, FILE * dtl));
COUNT wsigned __((int n, FILE * dvi, FILE * dtl));
S4 rsigned __((int n, FILE * dvi));
U4 runsigned __((int n, FILE * dvi));
COUNT wtable __((op_table table, int opcode, FILE * dvi, FILE * dtl));
COUNT setseq __((int opcode, FILE * dvi, FILE * dtl));
Void setpchar __((int charcode, FILE * dtl));
COUNT special __((FILE * dvi, FILE * dtl, int n));
COUNT fontdef __((FILE * dvi, FILE * dtl, int n));
COUNT preamble __((FILE * dvi, FILE * dtl));
COUNT postamble __((FILE * dvi, FILE * dtl));
COUNT postpost __((FILE * dvi, FILE * dtl));
String program; /* name of dv2dt program */
int
main
#ifdef __STDC__
(int argc, char * argv[])
#else
(argc, argv)
int argc;
char * argv[];
#endif
{
FILE * dvi = stdin;
FILE * dtl = stdout;
/* Watch out: C's standard library's string functions are dicey */
strncpy (program, argv[0], MAXSTRLEN);
if (argc > 1)
open_dvi (argv[1], &dvi);
if (argc > 2)
open_dtl (argv[2], &dtl);
dv2dt (dvi, dtl);
return 0; /* OK */
}
/* end main */
int
open_dvi
#ifdef __STDC__
(char * dvi_file, FILE ** pdvi)
#else
(dvi_file, pdvi)
char * dvi_file;
FILE ** pdvi;
#endif
/* I: dvi_file; I: pdvi; O: *pdvi. */
{
if (pdvi == NULL)
{
fprintf (stderr, "%s: address of dvi variable is NULL.\n", program);
exit (1);
}
*pdvi = fopen (dvi_file, "rb");
if (*pdvi == NULL)
{
fprintf (stderr, "%s: Cannot open \"%s\" for binary reading.\n",
program, dvi_file);
exit (1);
}
return 1; /* OK */
}
/* open_dvi */
int
open_dtl
#ifdef __STDC__
(char * dtl_file, FILE ** pdtl)
#else
(dtl_file, pdtl)
char * dtl_file;
FILE ** pdtl;
#endif
/* I: dtl_file; I: pdtl; O: *pdtl. */
{
if (pdtl == NULL)
{
fprintf (stderr, "%s: address of dtl variable is NULL.\n", program);
exit (1);
}
*pdtl = fopen (dtl_file, "w");
if (*pdtl == NULL)
{
fprintf (stderr, "%s: Cannot open \"%s\" for text writing.\n",
program, dtl_file);
exit (1);
}
return 1; /* OK */
}
/* open_dtl */
int
dv2dt
#ifdef __STDC__
(FILE * dvi, FILE * dtl)
#else
(dvi, dtl)
FILE * dvi;
FILE * dtl;
#endif
{
int opcode;
COUNT count; /* intended to count bytes to DVI file; as yet unused. */
PRINT_BCOM;
fprintf (dtl, "variety ");
/* fprintf (dtl, BMES); */
fprintf (dtl, VARIETY);
/* fprintf (dtl, EMES); */
PRINT_ECOM;
fprintf (dtl, "\n");
/* start counting DVI bytes */
count = 0;
while ((opcode = fgetc (dvi)) != EOF)
{
PRINT_BCOM; /* start of command and parameters */
if (opcode < 0 || opcode > 255)
{
count += 1;
fprintf (stderr, "%s: Non-byte from \"fgetc()\"!\n", program);
exit (1);
}
else if (opcode <= 127)
{
/* setchar commands */
/* count += 1; */
/* fprintf (dtl, "%s%d", SETCHAR, opcode); */
count +=
setseq (opcode, dvi, dtl);
}
else if (opcode >= 128 && opcode <= 170)
{
count +=
wtable (op_128_170, opcode, dvi, dtl);
}
else if (opcode >= 171 && opcode <= 234)
{
count += 1;
fprintf (dtl, "%s%d", FONTNUM, opcode - 171);
}
else if (opcode >= 235 && opcode <= 238)
{
count +=
wtable (fnt, opcode, dvi, dtl);
}
else if (opcode >= 239 && opcode <= 242)
{
count +=
special (dvi, dtl, opcode - 238);
}
else if (opcode >= 243 && opcode <= 246)
{
count +=
fontdef (dvi, dtl, opcode - 242);
}
else if (opcode == 247)
{
count +=
preamble (dvi, dtl);
}
else if (opcode == 248)
{
count +=
postamble (dvi, dtl);
}
else if (opcode == 249)
{
count +=
postpost (dvi, dtl);
}
else if (opcode >= 250 && opcode <= 255)
{
count += 1;
fprintf (dtl, "opcode%d", opcode);
}
else
{
count += 1;
fprintf (stderr, "%s: unknown byte.\n", program);
exit (1);
}
PRINT_ECOM; /* end of command and parameters */
fprintf (dtl, "\n");
if (fflush (dtl) == EOF)
{
fprintf (stderr, "%s: fflush on dtl file gave write error!\n", program);
exit (1);
}
} /* end while */
return 1; /* OK */
}
/* dv2dt */
COUNT
wunsigned
#ifdef __STDC__
(int n, FILE * dvi, FILE * dtl)
#else
(n, dvi, dtl)
int n;
FILE * dvi;
FILE * dtl;
#endif
{
U4 unum;
fprintf (dtl, " ");
unum = runsigned (n, dvi);
fprintf (dtl, UF4, unum);
return n;
}
/* end wunsigned */
COUNT
wsigned
#ifdef __STDC__
(int n, FILE * dvi, FILE * dtl)
#else
(n, dvi, dtl)
int n;
FILE * dvi;
FILE * dtl;
#endif
{
S4 snum;
fprintf (dtl, " ");
snum = rsigned (n, dvi);
fprintf (dtl, SF4, snum);
return n;
}
/* end wsigned */
U4
runsigned
#ifdef __STDC__
(int n, FILE * dvi)
#else
(n, dvi)
int n;
FILE * dvi;
#endif
/* read 1 <= n <= 4 bytes for an unsigned integer from dvi file */
/* DVI format uses Big-endian storage of numbers. */
{
U4 integer;
int ibyte = 0;
int i;
if (n < 1 || n > 4)
{
fprintf (stderr,
"%s: runsigned() asked for %d bytes. Must be 1 to 4.\n", program, n);
exit (1);
}
/* Following calculation works iff storage is big-endian. */
integer = 0;
for (i = 0; i < n; i++)
{
integer *= 256;
ibyte = fgetc (dvi);
integer += ibyte;
}
return integer;
}
/* end runsigned */
S4
rsigned
#ifdef __STDC__
(int n, FILE * dvi)
#else
(n, dvi)
int n;
FILE * dvi;
#endif
/* read 1 <= n <= 4 bytes for a signed integer from dvi file */
/* DVI format uses Big-endian storage of numbers. */
{
S4 integer;
int ibyte = 0;
int i;
if (n < 1 || n > 4)
{
fprintf (stderr,
"%s: rsigned() asked for %d bytes. Must be 1 to 4.\n", program, n);
exit (1);
}
/* Following calculation works iff storage is big-endian. */
integer = 0;
for (i = 0; i < n; i++)
{
integer *= 256;
ibyte = fgetc (dvi);
/* Big-endian implies sign byte is first byte. */
if (i == 0 && ibyte >= 128)
{
ibyte -= 256;
}
integer += ibyte;
}
return integer;
}
/* end rsigned */
COUNT
wtable
#ifdef __STDC__
(op_table table, int opcode, FILE * dvi, FILE * dtl)
#else
(table, opcode, dvi, dtl)
op_table table;
int opcode;
FILE * dvi;
FILE * dtl;
#endif
/* write command with given opcode in given table */
/* return number of DVI bytes in this command */
{
op_info op; /* pointer into table of operations and arguments */
COUNT bcount = 0; /* number of bytes in arguments of this opcode */
String args; /* arguments string */
int i; /* count of arguments read from args */
int pos; /* position in args */
/* Defensive programming. */
if (opcode < table.first || opcode > table.last)
{
fprintf (stderr,
"%s: opcode %d is outside table %s [ %d to %d ] !\n",
program, opcode, table.name, table.first, table.last);
exit (1);
}
op = table.list [opcode - table.first];
/* Further defensive programming. */
if (op.code != opcode)
{
fprintf (stderr, "%s: internal table %s wrong!\n", program, table.name);
exit (1);
}
bcount = 1;
fprintf (dtl, "%s", op.name);
/* NB: sscanf does an ungetc, */
/* so args must be writable. */
strncpy (args, op.args, MAXSTRLEN);
pos = 0;
for (i = 0; i < op.nargs; i++)
{
int argtype; /* sign and number of bytes in current argument */
int nconv; /* number of successful conversions from args */
int nread; /* number of bytes read from args */
nconv = sscanf (args + pos, "%d%n", &argtype, &nread);
/* internal consistency checks */
if (nconv != 1 || nread <= 0)
{
fprintf (stderr,
"%s: internal read of table %s failed!\n", program, table.name);
exit (1);
}
pos += nread;
bcount += ( argtype < 0 ?
wsigned (-argtype, dvi, dtl) :
wunsigned (argtype, dvi, dtl) ) ;
} /* end for */
return bcount;
}
/* wtable */
COUNT
setseq
#ifdef __STDC__
(int opcode, FILE * dvi, FILE * dtl)
#else
(opcode, dvi, dtl)
int opcode;
FILE * dvi;
FILE * dtl;
#endif
/* write a sequence of setchar commands */
/* return count of DVI bytes interpreted into DTL */
{
int charcode = opcode; /* fortuitous */
int ccount = 0;
if (!isprint (charcode))
{
ccount = 1;
fprintf (dtl, "%s%02X", SETCHAR, opcode);
}
else
{
/* start of sequence of font characters */
fprintf (dtl, BSEQ);
/* first character */
ccount = 1;
setpchar (charcode, dtl);
/* subsequent characters */
while ((opcode = fgetc (dvi)) != EOF)
{
if (opcode < 0 || opcode > 127)
{
break; /* not a setchar command, so sequence has ended */
}
charcode = opcode; /* fortuitous */
if (!isprint (charcode)) /* not printable ascii */
{
break; /* end of font character sequence, as for other commands */
}
else /* printable ASCII */
{
ccount += 1;
setpchar (charcode, dtl);
}
} /* end for loop */
/* prepare to reread opcode of next DVI command */
if (ungetc (opcode, dvi) == EOF)
{
fprintf (stderr, "setseq: cannot push back a byte\n");
exit (1);
}
/* end of sequence of font characters */
fprintf (dtl, ESEQ);
}
return ccount;
}
/* setseq */
Void
setpchar
#ifdef __STDC__
(int charcode, FILE * dtl)
#else
(charcode, dtl)
int charcode;
FILE * dtl;
#endif
/* set printable character */
{
switch (charcode)
{
case ESC_CHAR:
fprintf (dtl, "%c", ESC_CHAR);
fprintf (dtl, "%c", ESC_CHAR);
break;
case QUOTE_CHAR:
fprintf (dtl, "%c", ESC_CHAR);
fprintf (dtl, "%c", QUOTE_CHAR);
break;
case BSEQ_CHAR:
fprintf (dtl, "%c", ESC_CHAR);
fprintf (dtl, "%c", BSEQ_CHAR);
break;
case ESEQ_CHAR:
fprintf (dtl, "%c", ESC_CHAR);
fprintf (dtl, "%c", ESEQ_CHAR);
break;
default:
fprintf (dtl, "%c", charcode);
break;
}
}
/* setpchar */
COUNT
special
#ifdef __STDC__
(FILE * dvi, FILE * dtl, int n)
#else
(dvi, dtl, n)
FILE * dvi;
FILE * dtl;
int n;
#endif
/* read special 1 .. 4 from dvi and write in dtl */
/* return number of DVI bytes interpreted into DTL */
{
U4 k;
int i, ch;
if (n < 1 || n > 4)
{
fprintf (stderr, "%s: special %d, range is 1 to 4.\n", program, n);
exit (1);
}
fprintf (dtl, "%s%d", SPECIAL, n);
/* k[n] = length of special string */
fprintf (dtl, " ");
k = runsigned (n, dvi);
fprintf (dtl, UF4, k);
/* x[k] = special string */
fprintf (dtl, " ");
fprintf (dtl, "'");
for (i=0; i < k; i++)
{
ch = fgetc (dvi);
fprintf (dtl, "%c", ch);
}
fprintf (dtl, "'");
return (1 + n + k);
}
/* end special */
COUNT
fontdef
#ifdef __STDC__
(FILE * dvi, FILE * dtl, int n)
#else
(dvi, dtl, n)
FILE * dvi;
FILE * dtl;
int n;
#endif
/* read fontdef 1 .. 4 from dvi and write in dtl */
/* return number of DVI bytes interpreted into DTL */
{
U4 ku, c, s, d, a, l;
S4 ks;
int i, ch;
if (n < 1 || n > 4)
{
fprintf (stderr, "%s: font def %d, range is 1 to 4.\n", program, n);
exit (1);
}
fprintf (dtl, "%s%d", FONTDEF, n);
/* k[n] = font number */
fprintf (dtl, " ");
if (n == 4)
{
ks = rsigned (n, dvi);
fprintf (dtl, SF4, ks);
}
else
{
ku = runsigned (n, dvi);
fprintf (dtl, UF4, ku);
}
/* c[4] = checksum */
fprintf (dtl, " ");
c = runsigned (4, dvi);
/* fprintf (dtl, XF4, c); */
/* write in octal, to allow quick comparison with tftopl's output */
fprintf (dtl, OF4, c);
/* s[4] = scale factor */
fprintf (dtl, " ");
s = runsigned (4, dvi);
fprintf (dtl, UF4, s);
/* d[4] = design size */
fprintf (dtl, " ");
d = runsigned (4, dvi);
fprintf (dtl, UF4, d);
/* a[1] = length of area (directory) name */
fprintf (dtl, " ");
a = runsigned (1, dvi);
fprintf (dtl, UF4, a);
/* l[1] = length of font name */
fprintf (dtl, " ");
l = runsigned (1, dvi);
fprintf (dtl, UF4, l);
/* n[a+l] = font pathname = area (directory) + font */
fprintf (dtl, " ");
fprintf (dtl, "'");
for (i=0; i < a+l; i++)
{
ch = fgetc (dvi);
fprintf (dtl, "%c", ch);
}
fprintf (dtl, "'");
return (1 + n + 4 + 4 + 4 + 1 + 1 + a + l);
}
/* end fontdef */
COUNT
preamble
#ifdef __STDC__
(FILE * dvi, FILE * dtl)
#else
(dvi, dtl)
FILE * dvi;
FILE * dtl;
#endif
/* read preamble from dvi and write in dtl */
/* return number of DVI bytes interpreted into DTL */
{
U4 id, num, den, mag, k;
int i, ch;
fprintf (dtl, "pre");
/* i[1] = DVI format identification */
fprintf (dtl, " ");
id = runsigned (1, dvi);
fprintf (dtl, UF4, id);
/* num[4] = numerator of DVI unit */
fprintf (dtl, " ");
num = runsigned (4, dvi);
fprintf (dtl, UF4, num);
/* den[4] = denominator of DVI unit */
fprintf (dtl, " ");
den = runsigned (4, dvi);
fprintf (dtl, UF4, den);
/* mag[4] = 1000 x magnification */
fprintf (dtl, " ");
mag = runsigned (4, dvi);
fprintf (dtl, UF4, mag);
/* k[1] = length of comment */
fprintf (dtl, " ");
k = runsigned (1, dvi);
fprintf (dtl, UF4, k);
/* x[k] = comment string */
fprintf (dtl, " ");
fprintf (dtl, "'");
for (i=0; i < k; i++)
{
ch = fgetc (dvi);
fprintf (dtl, "%c", ch);
}
fprintf (dtl, "'");
return (1 + 1 + 4 + 4 + 4 + 1 + k);
}
/* end preamble */
COUNT
postamble
#ifdef __STDC__
(FILE * dvi, FILE * dtl)
#else
(dvi, dtl)
FILE * dvi;
FILE * dtl;
#endif
/* read postamble from dvi and write in dtl */
/* return number of bytes */
{
U4 p, num, den, mag, l, u, s, t;
fprintf (dtl, "post");
/* p[4] = pointer to final bop */
fprintf (dtl, " ");
p = runsigned (4, dvi);
fprintf (dtl, UF4, p);
/* num[4] = numerator of DVI unit */
fprintf (dtl, " ");
num = runsigned (4, dvi);
fprintf (dtl, UF4, num);
/* den[4] = denominator of DVI unit */
fprintf (dtl, " ");
den = runsigned (4, dvi);
fprintf (dtl, UF4, den);
/* mag[4] = 1000 x magnification */
fprintf (dtl, " ");
mag = runsigned (4, dvi);
fprintf (dtl, UF4, mag);
/* l[4] = height + depth of tallest page */
fprintf (dtl, " ");
l = runsigned (4, dvi);
fprintf (dtl, UF4, l);
/* u[4] = width of widest page */
fprintf (dtl, " ");
u = runsigned (4, dvi);
fprintf (dtl, UF4, u);
/* s[2] = maximum stack depth */
fprintf (dtl, " ");
s = runsigned (2, dvi);
fprintf (dtl, UF4, s);
/* t[2] = total number of pages (bop commands) */
fprintf (dtl, " ");
t = runsigned (2, dvi);
fprintf (dtl, UF4, t);
/* return (29); */
return (1 + 4 + 4 + 4 + 4 + 4 + 4 + 2 + 2);
}
/* end postamble */
COUNT
postpost
#ifdef __STDC__
(FILE * dvi, FILE * dtl)
#else
(dvi, dtl)
FILE * dvi;
FILE * dtl;
#endif
/* read post_post from dvi and write in dtl */
/* return number of bytes */
{
U4 q, id;
int b223; /* hope this is 8-bit clean */
int n223; /* number of "223" bytes in final padding */
fprintf (dtl, "post_post");
/* q[4] = pointer to post command */
fprintf (dtl, " ");
q = runsigned (4, dvi);
fprintf (dtl, UF4, q);
/* i[1] = DVI identification byte */
fprintf (dtl, " ");
id = runsigned (1, dvi);
fprintf (dtl, UF4, id);
/* final padding by "223" bytes */
/* hope this way of obtaining b223 is 8-bit clean */
for (n223 = 0; (b223 = fgetc (dvi)) == 223; n223++)
{
fprintf (dtl, " ");
fprintf (dtl, "%d", 223);
}
if (n223 < 4)
{
fprintf (stderr,
"%s: bad post_post: fewer than four \"223\" bytes.\n", program);
exit (1);
}
if (b223 != EOF)
{
fprintf (stderr,
"%s: bad post_post: doesn't end with a \"223\".\n", program);
exit (1);
}
return (1 + 4 + 1 + n223);
}
/* end postpost */
/* end of "dv2dt.c" */